/*
Copyright 2024 New Vector Ltd.
Copyright 2017 Vector Creations Ltd
Copyright 2014 OpenMarket Ltd

SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
 */

#import <UIKit/UIKit.h>
#import "MatrixKit.h"

#import "MasterTabBarController.h"
#import "JitsiViewController.h"

#import "RageShakeManager.h"

#import "ThemeService.h"
#import "UniversalLink.h"

@protocol Configurable;
@protocol LegacyAppDelegateDelegate;
@protocol SplitViewMasterViewControllerProtocol;
@class CallBar;
@class CallPresenter;
@class RoomNavigationParameters;
@class RoomPreviewNavigationParameters;
@class UniversalLinkParameters;

#pragma mark - Notifications
/**
 Posted when the user taps the clock status bar.
 */
extern NSString *const kAppDelegateDidTapStatusBarNotification;

/**
 Posted when the property 'isOffline' has changed. This property is related to the network reachability status.
 */
extern NSString *const kAppDelegateNetworkStatusDidChangeNotification;

extern NSString *const AppDelegateDidValidateEmailNotification;
extern NSString *const AppDelegateDidValidateEmailNotificationSIDKey;
extern NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey;

/**
 Posted when the property 'lastHandledUniversalLink' has changed. Notification object and userInfo will be nil.
 */
extern NSString *const AppDelegateUniversalLinkDidChangeNotification;

@interface LegacyAppDelegate : UIResponder <
UIApplicationDelegate,
UISplitViewControllerDelegate,
UINavigationControllerDelegate
>
{
    // background sync management
    void (^_completionHandler)(UIBackgroundFetchResult);
}

@property (weak, nonatomic) id<LegacyAppDelegateDelegate> delegate;

/**
 Application main view controller
 */
@property (nonatomic, readonly) UIViewController<SplitViewMasterViewControllerProtocol>* masterTabBarController;

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) UIAlertController *errorNotification;

@property (strong, nonatomic) NSString *appVersion;
@property (strong, nonatomic) NSString *build;

@property (nonatomic) BOOL isAppForeground;
@property (nonatomic) BOOL isOffline;

/**
 Last navigated room's identifier from a push notification.
 */
// TODO: This property is introduced to fix #3672. Remove it when a better solution revealed to the problem.
@property (nonatomic, copy) NSString *lastNavigatedRoomIdFromPush;


/**
 Let the AppDelegate handle and display self verification requests.
 Default is YES.
 */
@property (nonatomic) BOOL handleSelfVerificationRequest;

/**
 The navigation controller of the master view controller of the main split view controller.
 */
@property (nonatomic, readonly) UINavigationController *masterNavigationController;
/**
 The navigation controller of the detail view controller of the main split view controller (may be nil).
 */
@property (nonatomic, readonly) UINavigationController *secondaryNavigationController;

// Associated matrix sessions (empty by default).
@property (nonatomic, readonly) NSArray *mxSessions;

// Current selected room id. nil if no room is presently visible.
@property (strong, nonatomic) NSString *visibleRoomId;

/**
 Last handled universal link (url will be formatted for several hash keys).
 */
@property (nonatomic, copy, readonly) UniversalLink *lastHandledUniversalLink;

// New message sound id.
@property (nonatomic, readonly) SystemSoundID messageSound;

// Build Settings
@property (nonatomic, readonly) id<Configurable> configuration;

/**
 Call presenter instance. May be nil unless at least one session initialized.
 */
@property (nonatomic, strong, readonly) CallPresenter *callPresenter;

+ (instancetype)theDelegate;

#pragma mark - Push Notifications

/**
 Perform registration for remote notifications.

 @param completion the block to be executed when registration finished.
 */
- (void)registerForRemoteNotificationsWithCompletion:(void (^)(NSError *))completion;

#pragma mark - Application layout handling

- (void)restoreInitialDisplay:(void (^)(void))completion;

/**
 Replace the secondary view controller of the split view controller (if any) with the default empty details view controller.
 */
- (void)restoreEmptyDetailsViewController;

- (UIAlertController*)showErrorAsAlert:(NSError*)error;
- (UIAlertController*)showAlertWithTitle:(NSString*)title message:(NSString*)message;

#pragma mark - Matrix Sessions handling

// Add a matrix session.
- (void)addMatrixSession:(MXSession*)mxSession;

// Remove a matrix session.
- (void)removeMatrixSession:(MXSession*)mxSession;

// Mark all messages as read in the running matrix sessions.
- (void)markAllMessagesAsRead;

// Reload all running matrix sessions
- (void)reloadMatrixSessions:(BOOL)clearCache;

- (void)displayLogoutConfirmationForLink:(UniversalLink *)link
                              completion:(void (^)(BOOL loggedOut))completion;

/**
 Log out all the accounts after asking for a potential confirmation.
 Show the authentication screen on successful logout.

 @param askConfirmation tell whether a confirmation is required before logging out.
 @param completion the block to execute at the end of the operation.
 */
- (void)logoutWithConfirmation:(BOOL)askConfirmation completion:(void (^)(BOOL isLoggedOut))completion;

/**
 Log out all the accounts without confirmation.
 Show the authentication screen on successful logout.

 @param sendLogoutServerRequest Indicate whether send logout request to homeserver.
 @param completion the block to execute at the end of the operation.
 */
- (void)logoutSendingRequestServer:(BOOL)sendLogoutServerRequest
                        completion:(void (^)(BOOL isLoggedOut))completion;

/**
 Present incoming key verification request to accept.

 @param incomingKeyVerificationRequest The incoming key verification request.
 @param session The matrix session.
 @return Indicate NO if the key verification screen could not be presented.
 */
- (BOOL)presentIncomingKeyVerificationRequest:(id<MXKeyVerificationRequest>)incomingKeyVerificationRequest
                                    inSession:(MXSession*)session;

- (BOOL)presentUserVerificationForRoomMember:(MXRoomMember*)roomMember
                                     session:(MXSession*)mxSession
                                  completion:(void (^)(void))completion;

- (BOOL)presentCompleteSecurityForSession:(MXSession*)mxSession;

- (void)configureCallManagerIfRequiredForSession:(MXSession *)mxSession;

- (void)authenticationDidComplete;

#pragma mark - Matrix Accounts handling

- (void)selectMatrixAccount:(void (^)(MXKAccount *selectedAccount))onSelection;

#pragma mark - Matrix Room handling

// Show a room and jump to the given event if event id is not nil otherwise go to last messages.
- (void)showRoomWithParameters:(RoomNavigationParameters*)parameters completion:(void (^)(void))completion;

- (void)showRoomWithParameters:(RoomNavigationParameters*)parameters;

// Restore display and show the room
- (void)showRoom:(NSString*)roomId andEventId:(NSString*)eventId withMatrixSession:(MXSession*)mxSession;

// Show room preview
- (void)showRoomPreviewWithParameters:(RoomPreviewNavigationParameters*)parameters completion:(void (^)(void))completion;

- (void)showRoomPreviewWithParameters:(RoomPreviewNavigationParameters*)parameters;

// Restore display and show the room preview
- (void)showRoomPreview:(RoomPreviewData*)roomPreviewData;

// Display a new direct room with a target user without associated room.
- (void)showNewDirectChat:(NSString*)userId withMatrixSession:(MXSession*)mxSession completion:(void (^)(void))completion;

// Creates a new direct room with the provided user id
- (void)createDirectChatWithUserId:(NSString*)userId completion:(void (^)(NSString *roomId))completion;

// Reopen an existing direct room with this userId or creates a new one (if it doesn't exist)
- (void)startDirectChatWithUserId:(NSString*)userId completion:(void (^)(void))completion;

/**
 Process the fragment part of a vector.im link.

 @param fragment the fragment part of the universal link.
 @param universalLink the original universal link.
 @return YES in case of processing success.
 */
- (BOOL)handleUniversalLinkFragment:(NSString*)fragment fromLink:(UniversalLink*)universalLink;

/**
 Process the URL of a vector.im link.

 @param universalLinkURL the universal link URL.
 @return YES in case of processing success.
 */
- (BOOL)handleUniversalLinkURL:(NSURL*)universalLinkURL;

/**
 Process universal link.
 
 @param parameters the universal link parameters.
 @return YES in case of processing success.
 */
- (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)parameters;

/**
 Open the dedicated space with the given ID.
 
 This method will open only joined or invited spaces.
 @note this method is temporary and should be moved to a dedicated coordinator
 
 @param spaceId ID of the space.
 */
- (void)openSpaceWithId:(NSString*)spaceId;

#pragma mark - App version management

/**
 Check for app version related informations to display
*/
- (void)checkAppVersion;

@end

@protocol LegacyAppDelegateDelegate <NSObject>

- (void)legacyAppDelegate:(LegacyAppDelegate*)legacyAppDelegate wantsToPopToHomeViewControllerAnimated:(BOOL)animated completion:(void (^)(void))completion;
- (void)legacyAppDelegateRestoreEmptyDetailsViewController:(LegacyAppDelegate*)legacyAppDelegate;

- (void)legacyAppDelegate:(LegacyAppDelegate*)legacyAppDelegate didAddMatrixSession:(MXSession*)session;

- (void)legacyAppDelegate:(LegacyAppDelegate*)legacyAppDelegate didRemoveMatrixSession:(MXSession*)session;

- (void)legacyAppDelegate:(LegacyAppDelegate*)legacyAppDelegate didAddAccount:(MXKAccount*)account;

- (void)legacyAppDelegate:(LegacyAppDelegate*)legacyAppDelegate didRemoveAccount:(MXKAccount*)account;

- (void)legacyAppDelegate:(LegacyAppDelegate*)legacyAppDelegate didNavigateToSpaceWithId:(NSString*)spaceId;

@end
